home *** CD-ROM | disk | FTP | other *** search
Text File | 1990-08-16 | 31.2 KB | 1,115 lines |
- /***************************************************************************
- *
- * Microcosm.c
- *
- * Archimedes
- *
- * Microcosm program - Public Domain release
- * 5 June 1990 : version 1
- *
- * Written by....
- * Michael Spearpoint
- * 3 Lawrence Crescent
- * Edgware
- * Middx HA8 5PB
- *
- ***************************************************************************/
-
- #include <stdio.h>
- #include <string.h>
- #include <math.h>
- #include <stdlib.h>
- #include <time.h>
-
- #include "res.h"
- #include "resspr.h"
- #include "bbc.h"
-
- /**************************************************************************/
- /* Define global variables and format of any functions */
-
- #define VERSION "version 1 "
-
- #define GRAPHICS TRUE /* Draw creature graphics code */
- #define WRAP_AROUND FALSE /* Wrap around movement code */
-
- /* Define screen plotting factors */
- #define SCREEN_X 22 /* Screen plotting x factor */
- #define SCREEN_Y 22 /* Screen plotting y factor */
- #define ORIGIN_X 10 /* Origin of graph - x coordinate */
- #define ORIGIN_Y 630 /* Origin of graph - y coordinate */
- #define WIDTH 900 /* Graph width */
-
- #define DIRECTIONS 8 /* Area to check for food etc - set to 8 or 4
- * When 4 - checks n,e,s,w
- * When 8 - checks n,ne,nw,e,w,s,se,sw */
-
- #define X_MAX 55 /* Number of grid cells - x direction */
- #define Y_MAX 27 /* Number of grid cells - y direction */
- #define CREATURE_TYPES 10 /* Max number of creature types */
- #define MAX_FOOD 4 /* Number of different creature types
- * that a particular type can eat */
-
- #define MAX_CREATURES (X_MAX * Y_MAX)
-
- #define DEAD 0
- #define EMPTY 0
- #define FAIL -1
-
- #define RANDOM(A) ((A + 1) * (float)rand() / (float)RAND_MAX)
-
- /* Palette colours */
- enum { WHITE, GREY1, GREY2, GREY3, GREY4, GREY5, GREY6, BLACK,
- BLUE, YELLOW, GREEN, RED, CREAM, DARK_GREEN, ORANGE, CYAN };
-
- /**************************************************************************/
- /* Define procedures */
-
- /* Initialisation procedures */
- void initialise(void);
- void create_populations(void);
- void draw_axes(void);
-
- /* File reading procedures */
- BOOL load_file(void);
- void read_data(int);
- void read_general_data(void);
- void read_initial_positions(void);
-
- /* Main processing procedures */
- void main_loop(void);
- void process_creatures(void);
- void update_graph(int);
-
- /* Creature processing procedures */
- void move_creature(int, int);
- void consume_strength(int, int);
- void feed(int, int);
- void birth(int, int);
-
- /* General routines */
- BOOL valid_location(char, char);
- int find_creature_at(char, char);
- int find_free_creature(void);
-
- /**************************************************************************/
-
- char grid[X_MAX + 1][Y_MAX + 1] = EMPTY;
- int pop_tots[CREATURE_TYPES + 1] = 0;
- int old_pop_tots[CREATURE_TYPES + 1] = 0;
- FILE *read;
- sprite_area *sprite_bk;
-
- /* Global data structure */
- struct global
- {
- int iterations;
- int wait;
- BOOL random;
- BOOL draw_creatures;
- BOOL draw_overall;
- int total_types;
- float graph_scale;
- } global = { 0, 0, TRUE, TRUE, TRUE, 1, (float) 1 };
-
- /* Creature type structure */
- struct type
- {
- char name[11]; /* Creature / sprite name */
- int initial_number;/* Initial number for random start */
- char move; /* Movement rate */
- int max_str; /* Max strength for creature */
- signed char consumption; /* Strength consumption per iteration */
- int food; /* Valid food types for this creature type */
- int food_value; /* Food value when creature is eaten */
- int adult; /* Age at which creature can give birth */
- int birth_str; /* Minimum strength for birth */
- char child_str; /* Percentage of parents strength to child */
- int decay; /* Creature type formed by the death of type */
- }
- type[CREATURE_TYPES];
-
- /* Individual creature */
- struct creature
- {
- char type; /* Creature type */
- char x; /* x coord */
- char y; /* y coord */
- signed char dx; /* Movement in x dir +1,0,-1 */
- signed char dy; /* Movement in y dir +1,0,-1 */
- int str; /* Current strength */
- char move_c; /* Movement counter */
- int age; /* Age in iterations */
- }
- creature[MAX_CREATURES + 1] =
- {
- 0, 0, 0, 0, 0, 0, 0, 0
- };
-
- #if DIRECTIONS == 8
- struct loc_offset
- {
- signed char dx;
- signed char dy;
- }
- loc_offset[DIRECTIONS] =
- { -1,-1, 0,-1, +1,-1, -1,0, +1,0, -1,+1, 0,+1, +1,+1 };
- #endif
-
- #if DIRECTIONS == 4
- struct loc_offset
- {
- signed char dx;
- signed char dy;
- }
- loc_offset[DIRECTIONS] =
- { 0,-1, -1,0, +1,0, 0,+1, };
- #endif
-
-
- /**************************************************************************/
-
-
-
- /**************************************************************************/
- /* INITIALISATION AND FILE READING PROCEDURES */
- /**************************************************************************/
- /* Initialise */
-
- void initialise(void)
-
- {
- res_init("Microcosm"); /* Find resources */
- resspr_init(); /* Find sprite file */
- sprite_bk = resspr_area();
-
- /* Set up screen mode and load palette */
- bbc_mode(12);
- system("<Microcosm$Dir>.Palette");
- bbc_colour(128 + BLACK);
- bbc_colour(WHITE);
- bbc_cls();
-
- /* Reseed randomiser */
- srand(clock());
-
-
- /* Start up message */
- bbc_tab(22,8);
- printf("Microcosm program (Public Domain)");
- bbc_tab(26,10);
- printf("%s",VERSION);
- printf("%s",__DATE__);
- bbc_tab(28,12);
- printf("Michael Spearpoint");
- bbc_tab(2,30);
- printf("Press any key....");
- bbc_get();
- bbc_cls();
- }
-
- /**************************************************************************/
- /* Load set up file */
-
- BOOL load_file(void)
-
- {
- char *file = "<Microcosm$Dir>.SetUp";
- BOOL comment = FALSE;
- char chr;
- int data_type;
-
-
- read = fopen(file,"r");
-
- /* Found file ? */
- if (read == NULL)
- {
- printf("Error - SetUp file not found, program terminated");
- return(FALSE);
- }
-
- /* Read file down to # character */
- while ((chr = fgetc(read)) != '#')
- {
- switch (chr)
- {
- case '*' : comment = !comment;
- break;
-
- case '}' : if (comment == FALSE)
- { read_general_data(); }
- break;
-
- case '>' : if (comment == FALSE)
- {
- fscanf(read,"%i",&data_type);
- read_data(data_type);
- }
- break;
-
- default : break;
- }
- }
-
- fclose(read);
- return(TRUE);
- }
-
- /**************************************************************************/
- /* Read general data from file */
-
- void read_general_data(void)
-
- {
- static int count = 0;
- char chr;
-
- ++count;
-
- switch (count)
- {
- case 1 : fscanf(read,"%i", &global.total_types);
- if (global.total_types > CREATURE_TYPES)
- {
- printf("Error - Too many creature types");
- exit(NULL);
- }
- break;
-
- case 2 : fscanf(read,"%i", &global.iterations);
- break;
-
- case 3 : do {
- fscanf(read,"%c",&chr);
- } while (chr == ' ');
- global.random = (chr == 'Y') ? TRUE : FALSE;
- read_initial_positions();
- break;
-
- case 4 : fscanf(read,"%i",&global.wait);
- break;
-
- case 5 : fscanf(read,"%f",&global.graph_scale);
- break;
-
- case 6 : do {
- fscanf(read,"%c",&chr);
- } while (chr == ' ');
- global.draw_creatures = (chr == 'Y') ? TRUE : FALSE;
- break;
-
- case 7 : do {
- fscanf(read,"%c",&chr);
- } while (chr == ' ');
- global.draw_overall = (chr == 'Y') ? TRUE : FALSE;
- break;
-
- default : break;
- }
- }
-
- /**************************************************************************/
- /* Read the initial creature positions from the setup file */
-
- void read_initial_positions(void)
-
- {
- int x = -4, y = Y_MAX;
- int c_type;
- char chr;
-
- /* Random creature set up ? */
- if (global.random == TRUE)
- {
- /* Search file for next '}' character */
- while ((chr = fgetc(read)) != '}') { }
- ungetc('}',read);
- }
- else
- {
- /* Find the '>' character which defines the beginning of the table */
- while ((chr = fgetc(read)) != '>') { }
-
- while ((chr = fgetc(read)) != '*')
- {
- switch (chr)
- {
- /* Increment x coord */
- case ' ' : ++x;
- break;
-
- /* Next line of table - reset x and decrement y coords */
- case '\r' :
- case '\n' : x = -4; --y;
- break;
-
- /* Character found - check that it is valid */
- default : c_type = ((int) chr - 'a' + 1);
- if(c_type >= 0 && c_type <= global.total_types)
- {
- /* Position creature if the location
- * is on the grid */
- if (valid_location(x,y) == TRUE)
- { grid[x][y] = c_type; }
- }
- ++x;
- break;
- }
- }
-
- /* Put the '*' character back into the file buffer */
- ungetc('*',read);
-
- }
- }
-
- /**************************************************************************/
- /* Read data from the SetUp file */
-
- void read_data(int data_type)
-
- #define NAME 0
- #define INITIAL_NO 1
- #define MOVE 2
- #define MAX_STR 3
- #define CONSUMPTION 4
- #define FOOD_VALUE 5
- #define ADULT 6
- #define BIRTH_STR 7
- #define FOOD 8
- #define CHILD_STR 9
- #define DECAY 10
-
- {
- int c, n;
- int c_type;
- char chr;
-
-
- switch (data_type)
- {
- case NAME : for (c = 1; c <= global.total_types; c++)
- {
- fscanf(read,"%s",type[c].name);
- if (strlen(type[c].name) > 10)
- {
- printf("Error - Sprite name too long");
- exit(NULL);
- }
- }
- break;
-
-
- case INITIAL_NO : for (c = 1; c <= global.total_types; c++)
- {
- fscanf(read,"%i",&type[c].initial_number);
- }
- break;
-
-
- case MOVE : for (c = 1; c <= global.total_types; c++)
- {
- fscanf(read,"%i",&type[c].move);
- if (type[c].move < 0)
- {
- printf("Error - ");
- printf("Movement rate must be 0 or more");
- exit(NULL);
- }
- }
- break;
-
-
- case MAX_STR : for (c = 1; c <= global.total_types; c++)
- {
- fscanf(read,"%i",&type[c].max_str);
- if (type[c].max_str < 1)
- {
- printf("Error - ");
- printf("Max strength must be 1 or more");
- exit(NULL);
- }
- }
- break;
-
-
- case CONSUMPTION : for (c = 1; c <= global.total_types; c++)
- {
- fscanf(read,"%i",&type[c].consumption);
- }
- break;
-
-
- case FOOD_VALUE : for (c = 1; c <= global.total_types; c++)
- {
- fscanf(read,"%i",&type[c].food_value);
- }
- break;
-
-
- case ADULT : for (c = 1; c <= global.total_types; c++)
- {
- fscanf(read,"%i",&type[c].adult);
- }
- break;
-
-
- case BIRTH_STR : for (c = 1; c <= global.total_types; c++)
- {
- fscanf(read,"%i",&type[c].birth_str);
- }
- break;
-
-
- case CHILD_STR : for (c = 1; c <= global.total_types; c++)
- {
- fscanf(read,"%i",&type[c].child_str);
- }
- break;
-
-
- case DECAY : for (c = 1; c <= global.total_types; c++)
- {
- while ((chr = fgetc(read)) == ' ') { }
- c_type = (int) chr - 'a' + 1;
- if (c_type > 0 && c_type <= CREATURE_TYPES)
- { type[c].decay = (char) c_type; }
- }
- break;
-
-
- case FOOD : for (c = 1; c <= global.total_types; c++)
- {
- for(n = 0; n < MAX_FOOD; n++)
- {
- while ((chr = fgetc(read)) == ' ') { }
- c_type = (int) chr - 'a' + 1;
- if(c_type > 0 && c_type <= CREATURE_TYPES)
- {
- if(c_type != ('.' - 'a' + 1))
- {type[c].food +=(int)(pow(2,c_type));}
- }
- }
- }
- break;
-
- default : break;
- }
- }
-
- /**************************************************************************/
- /* Create the initial creature populations */
-
- void create_populations(void)
-
- {
- int c_type, c, x, y;
- int number = 0;
- sprite_id id;
-
-
- /* If random set up - fill grid */
- if (global.random == TRUE)
- {
- for (c_type = 1; c_type <= global.total_types; c_type++)
- {
- for (c = 1; c <= type[c_type].initial_number; c++)
- {
- /* Find an empty location on the grid */
- do {
- x = (int) RANDOM(X_MAX - 2) + 1;
- y = (int) RANDOM(Y_MAX - 2) + 1;
- } while (grid[x][y] != EMPTY);
-
- /* Put creature type onto the grid */
- grid[x][y] = c_type;
- }
- }
- }
-
-
- /* Search grid and set up the initial conditions for each creature */
- for (x = 1; x <= X_MAX; x++)
- {
- for (y = 1; y <= Y_MAX; y++)
- {
- if ((c_type = grid[x][y]) != EMPTY)
- {
- id.s.name = type[c_type].name;
- ++number;
- ++pop_tots[c_type];
- ++old_pop_tots[c_type];
-
-
- /* Set up data */
- creature[number].type = c_type;
- creature[number].x = x;
- creature[number].y = y;
- creature[number].dx = (signed char) (RANDOM(2)) - 1;
- creature[number].dy = (signed char) (RANDOM(2)) - 1;
- creature[number].str=(int)(1+RANDOM(type[c_type].max_str/2));
- creature[number].move_c=(int) (1 + RANDOM(type[c_type].move));
- creature[number].age = (int) (1 + RANDOM(type[c_type].adult));
-
- /* Draw sprite on the screen */
- #if GRAPHICS == TRUE
- if (global.draw_creatures == TRUE)
- {
- sprite_put_given(sprite_bk, &id, 0,
- x * SCREEN_X, y * SCREEN_Y);
- }
- #endif
- }
- }
- }
-
- }
-
- /**************************************************************************/
- /* Draw graph axes */
-
- void draw_axes(void)
-
- {
- int n;
- sprite_id id;
-
- bbc_gcol(0,GREY1);
- bbc_move(ORIGIN_X,ORIGIN_Y);
- bbc_drawby(0,1000 - ORIGIN_Y);
- bbc_move(ORIGIN_X,ORIGIN_Y);
- bbc_drawby(WIDTH,0);
-
- bbc_colour(GREY2);
- bbc_tab(63,0);
- printf("Iteration");
- bbc_colour(WHITE);
- bbc_tab(64,1);
- printf("Total");
-
- for (n = 1; n <= global.total_types; n++)
- {
- bbc_colour(BLUE + n);
- bbc_tab(64,n + 1);
- printf("%s",type[n].name);
- bbc_tab(73,n + 1);
- printf("%i",pop_tots[n]);
-
- #if GRAPHICS == TRUE
- if (global.draw_creatures == TRUE)
- {
- id.s.name = type[n].name;
- sprite_put_given(sprite_bk, &id, 0, 970,968 - (n * 32));
- }
- #endif
- }
- }
-
- /**************************************************************************/
-
-
-
- /**************************************************************************/
- /* MAIN PROCESSING */
- /**************************************************************************/
- /* Main processing loop */
-
- void main_loop(void)
-
- {
- int loop;
-
- for (loop = 1; loop <= global.iterations; loop++)
- {
- process_creatures();
- update_graph(loop);
- srand(clock());
- }
-
- }
-
- /**************************************************************************/
- /* Do one iteration */
-
- void process_creatures(void)
-
- {
- int pause;
- int c;
- int t;
-
- for (c = 1; c <= MAX_CREATURES; c++)
- {
- if (creature[c].str != DEAD)
- {
- /* Get the type of creature */
- t = creature[c].type;
-
- /* Age the creature */
- ++creature[c].age;
-
- /* Update movement counter */
- if (++creature[c].move_c >= type[t].move && type[t].move != 0)
- { move_creature(c, t); }
-
- /* Check for food */
- feed(c, t);
-
- /* Consume strength */
- consume_strength(c, t);
-
- /* Give birth to child ? */
- birth(c, t);
-
- }
-
- /* Pause */
- for (pause = 0; pause <= (global.wait * 100); pause++) { }
-
- }
- }
-
- /**************************************************************************/
- /* Update the graph */
-
- void update_graph(int loop)
-
- {
- static int x = 0;
- static int old_overall_total = 0;
- int n;
- int dead = 0;
- int overall_total = 0;
-
-
- /* Check for end of graph */
- if (++x >= WIDTH)
- {
- x = 1;
- bbc_gcol(0,BLACK);
- bbc_rectanglefill(ORIGIN_X + 2,ORIGIN_Y + 4,WIDTH,1000 - ORIGIN_Y + 24);
- }
-
-
- /* Print current iteration */
- bbc_colour(GREY2);
- bbc_tab(73,0);
- printf("%i",loop);
-
-
- /* Plot graph and update population totals */
- for (n = 1; n <= global.total_types; n++)
- {
- if (pop_tots[n] > NULL)
- {
- bbc_gcol(0, BLUE + n);
- bbc_move(ORIGIN_X + x - 1, (int)
- (ORIGIN_Y + 4 + (global.graph_scale * old_pop_tots[n])));
- bbc_draw(ORIGIN_X + x, (int)
- (ORIGIN_Y + 4 + (global.graph_scale * pop_tots[n])));
- }
- else
- {
- ++dead;
- }
-
- bbc_colour(BLUE + n);
- bbc_tab(73,n + 1);
- printf("%i ",pop_tots[n]);
-
- overall_total += pop_tots[n];
- old_pop_tots[n] = pop_tots[n];
-
- }
-
- /* Plot overall creature total */
- bbc_colour(WHITE);
- bbc_tab(73,1);
- printf("%i ",overall_total);
- if (global.draw_overall == TRUE)
- {
- bbc_gcol(0,WHITE);
- bbc_move(ORIGIN_X + x - 1, (int)
- (ORIGIN_Y + 4 + (global.graph_scale * old_overall_total)));
- bbc_draw(ORIGIN_X + x, (int)
- (ORIGIN_Y + 4 + (global.graph_scale * overall_total)));
- old_overall_total = overall_total;
- }
-
-
- /* All creatures dead - end program */
- if (dead == global.total_types)
- {
- bbc_tab(0,29);
- exit(NULL);
- }
- }
-
- /**************************************************************************/
- /* Move a creature */
-
- void move_creature(int c_number, int c_type)
-
- {
- char oldx, oldy;
- char newx, newy;
- sprite_id id;
-
-
- /* Reset movement counter */
- creature[c_number].move_c = 0;
-
-
- /* Choose new dx and dy ? */
- if ((int) (RANDOM(10)) == 10)
- {
- creature[c_number].dx = (signed char) (RANDOM(2)) - 1;
- creature[c_number].dy = (signed char) (RANDOM(2)) - 1;
- }
-
-
- /* Determine new location */
- oldx = creature[c_number].x;
- oldy = creature[c_number].y;
- newx = oldx + creature[c_number].dx;
- newy = oldy + creature[c_number].dy;
-
- #if WRAP_AROUND == TRUE
- if (newx > X_MAX) { newx = 1; }
- if (newx == 0) { newx = X_MAX; }
- if (newy > Y_MAX) { newy = 1; }
- if (newy == 0) { newy = Y_MAX; }
- #endif
-
- #if WRAP_AROUND == FALSE
- if (newx > X_MAX) { newx = X_MAX; }
- if (newx == 0) { newx = 1; }
- if (newy > Y_MAX) { newy = Y_MAX; }
- if (newy == 0) { newy = 1; }
- #endif
-
- /* If the new location is empty then move the creature */
- if (grid[newx][newy] == EMPTY)
- {
- /* Remove creature from old location */
- grid[oldx][oldy] = EMPTY;
- #if GRAPHICS == TRUE
- if (global.draw_creatures == TRUE)
- {
- id.s.name = "blank";
- sprite_put_given(sprite_bk, &id, 0,
- oldx * SCREEN_X, oldy * SCREEN_Y);
- }
- #endif
-
-
- /* Draw creature in the new location */
- grid[newx][newy] = c_type;
- #if GRAPHICS == TRUE
- if (global.draw_creatures == TRUE)
- {
- id.s.name = type[c_type].name;
- sprite_put_given(sprite_bk, &id, 0,
- newx * SCREEN_X, newy * SCREEN_Y);
- }
- #endif
-
-
- /* Update the creatures current coordinates */
- creature[c_number].x = newx;
- creature[c_number].y = newy;
- }
- }
-
- /**************************************************************************/
- /* Creature consumes strength */
-
- void consume_strength(int c_number, int c_type)
-
- {
- int dir;
- int decay_number;
- int decay_type;
- int x, y;
- int dx,dy;
- sprite_id id;
-
-
- /* Consume strength. If the strength falls to zero or less
- * the kill the creature */
- if ((creature[c_number].str -= type[c_type].consumption) <= 0)
- {
- x = creature[c_number].x;
- y = creature[c_number].y;
-
- /* Kill the creature */
- creature[c_number].str = DEAD;
- --pop_tots[c_type];
- grid[x][y] = EMPTY;
-
- #if GRAPHICS == TRUE
- if (global.draw_creatures == TRUE)
- {
- id.s.name = "blank";
- sprite_put_given(sprite_bk, &id, 0, x * SCREEN_X, y * SCREEN_Y);
- }
- #endif
-
-
- /* Does the death of this creature form any decay products ? */
- decay_type = type[c_type].decay;
- if (decay_type != NULL)
- {
- for (dir = 0; dir < DIRECTIONS; dir++)
- {
- dx = x + loc_offset[dir].dx;
- dy = y + loc_offset[dir].dy;
-
- /* Is the cell location valid ? */
- if (valid_location(dx,dy) == TRUE)
- {
- /* Is cell empty ? */
- if (grid[dx][dy] == EMPTY)
- {
- /* Resurrect a dead creature (except if FAIL) */
- if ((decay_number = find_free_creature()) != FAIL)
- {
- /* Create decay creature */
- creature[decay_number].str =
- 1 + (int) RANDOM(type[decay_type].max_str);
- creature[decay_number].age = 1;
- creature[decay_number].type = decay_type;
- creature[decay_number].move_c = 0;
- creature[decay_number].x = dx;
- creature[decay_number].y = dy;
- creature[decay_number].dx =
- (signed char) (RANDOM(2)) - 1;
- creature[decay_number].dy =
- (signed char) (RANDOM(2)) - 1;
- ++pop_tots[decay_type];
-
-
- /* Fill grid and draw decay creature on screen */
- grid[dx][dy] = decay_type;
-
- #if GRAPHICS == TRUE
- if (global.draw_creatures == TRUE)
- {
- id.s.name = type[decay_type].name;
- sprite_put_given(sprite_bk, &id, 0,
- dx * SCREEN_X, dy * SCREEN_Y);
- }
- #endif
- }
- }
- }
- }
- }
- }
- }
-
- /**************************************************************************/
- /* Check surrounding locations for possible food */
-
- void feed(int c_number, int c_type)
-
- {
- int n;
- int x, y;
- int dx,dy;
- int nbour_type;
- int nbour_number;
- sprite_id id;
-
-
- x = creature[c_number].x;
- y = creature[c_number].y;
-
- for (n = 0; n < DIRECTIONS; n++)
- {
- dx = x + loc_offset[n].dx;
- dy = y + loc_offset[n].dy;
-
-
- /* Check that the neighbouring cell is on grid */
- if (valid_location(dx,dy) == TRUE)
- {
- /* Get creature type in the cell */
- nbour_type = grid[dx][dy];
- if (nbour_type != EMPTY)
- {
- /* Does this creature eat neighbouring type ? */
- if ((type[c_type].food & (int) (pow(2,nbour_type))) != NULL)
- {
- /* Find the neighbour's number */
- if ((nbour_number = find_creature_at(dx,dy)) != FAIL)
- {
- /* Eat the neighbour */
- creature[c_number].str += type[nbour_type].food_value;
- if (creature[c_number].str > type[c_type].max_str)
- { creature[c_number].str = type[c_type].max_str; }
- creature[nbour_number].str = DEAD;
- --pop_tots[nbour_type];
-
- /* Remove neighbour from grid and screen */
- grid[dx][dy] = EMPTY;
-
- #if GRAPHICS == TRUE
- if (global.draw_creatures == TRUE)
- {
- id.s.name = "blank";
- sprite_put_given(sprite_bk, &id, 0,
- dx * SCREEN_X, dy * SCREEN_Y);
- }
- #endif
- }
- }
- }
- }
- }
-
- }
-
- /**************************************************************************/
- /* Give birth to a child */
-
- void birth(int c_number, int c_type)
-
- {
- int dir;
- int child_number;
- int x, y;
- sprite_id id;
-
-
- /* Can the creature have children and is the creature an adult ? */
- if (type[c_type].adult > 0 && creature[c_number].age >= type[c_type].adult)
- {
- /* Has the creature enough strength ? */
- if (creature[c_number].str >= type[c_type].birth_str)
- {
- /* Choose and random neighbouring cell - check that it is valid */
- dir = (int) RANDOM(DIRECTIONS - 1);
- x = creature[c_number].x + loc_offset[dir].dx;
- y = creature[c_number].y + loc_offset[dir].dy;
- if (valid_location(x,y) == TRUE)
- {
- /* Check that cell is empty */
- if (grid[x][y] == EMPTY)
- {
- /* Resurrect a dead creature (except if FAIL) */
- if ((child_number = find_free_creature()) != FAIL)
- {
- /* Create child */
- creature[child_number].str = creature[c_number].str *
- type[c_type].child_str / 100;
- creature[child_number].age = 1;
- creature[child_number].type = c_type;
- creature[child_number].move_c = 0;
- creature[child_number].x = x;
- creature[child_number].y = y;
- creature[child_number].dx=(signed char) (RANDOM(2)) - 1;
- creature[child_number].dy=(signed char) (RANDOM(2)) - 1;
- ++pop_tots[c_type];
-
-
- /* Adjust parents data */
- creature[c_number].str = creature[c_number].str *
- (100 - type[c_type].child_str) / 100;
-
-
- /* Fill grid and draw child creature on screen */
- grid[x][y] = c_type;
-
- #if GRAPHICS == TRUE
- if (global.draw_creatures == TRUE)
- {
- id.s.name = type[c_type].name;
- sprite_put_given(sprite_bk, &id, 0,
- x * SCREEN_X, y * SCREEN_Y);
- }
- #endif
- }
- }
- }
- }
- }
- }
-
- /**************************************************************************/
-
-
-
-
- /**************************************************************************/
- /* GENERAL ROUTINES */
- /**************************************************************************/
- /* Check that location is valid ie on the grid */
-
- BOOL valid_location(char x, char y)
-
- {
- if (x > X_MAX || x < 1 || y > Y_MAX || y < 1) { return(FALSE); }
-
- return(TRUE);
- }
-
- /**************************************************************************/
- /* Find the creature number at a given location or return FAIL
- * if not found */
-
- int find_creature_at(char x, char y)
-
- {
- int n;
-
- for (n = 1; n <= MAX_CREATURES; n++)
- {
- if (creature[n].str != DEAD)
- {
- if (creature[n].x == x && creature[n].y == y)
- { return(n); }
- }
- }
-
- return(FAIL);
- }
-
- /**************************************************************************/
- /* Return a dead creature for reuse or FAIL if not available */
-
- int find_free_creature(void)
-
- {
- int n;
-
- for (n = 1; n <= MAX_CREATURES; n++)
- {
- if (creature[n].str == DEAD) { return(n); }
- }
-
- return(FAIL);
-
- }
-
- /**************************************************************************/
- /* Main procedure */
-
- int main()
-
- {
- initialise();
- if (load_file() == FALSE) { return(NULL); }
- create_populations();
- draw_axes();
- main_loop();
-
- bbc_tab(0,29);
- return(NULL);
- }
-
- /**************************************************************************/
-
-
-